package main

import (
	"cybertwin/ue"
	"cybertwin/utils/protocol"
	"cybertwin/utils/timer"
	"fmt"
	"github.com/panjf2000/gnet/v2"
	log "github.com/sirupsen/logrus"
	"sync"
	"time"
)

var apClient ue.ApClient
var ctClient ue.CybertwinClient

const (
	AP_URL = "127.0.0.1:8082"
	ueid   = "ue_9384d910-08d9-4bc8-89ac-0cec35b89805"
	hid    = "f1395ba8c6302eb33eae96cdb4ab8219078de444199c2e4fb52e860441e2c58cd7666a381bf0b8f246082ece7156547301b570d52aae9ed113ff806d913abd58"
)

func runAPClient(ueid string, hid string) (err error) {
	//dir, err := os.Getwd()
	wg := &sync.WaitGroup{}
	wg.Add(1)

	apClient = ue.ApClient{
		Ueid: ueid,
		Hid:  hid,
		Wg:   wg,
	}
	cli, err := gnet.NewClient(&apClient)
	if err != nil {
		log.Errorln("runAPClient:", err.Error())
		return
	}
	err = cli.Start()
	_, err = cli.Dial("tcp", AP_URL)
	if err != nil {
		log.Errorln("runAPClient:", err.Error())
		return
	}

	wg.Wait()
	cli.Stop()

	return
}

// runCyberTwinClient 入参t在正常情况下传入nil即可。
func runCyberTwinClient(t *timer.Timer) (conn gnet.Conn, cli *gnet.Client, err error) {

	wg := &sync.WaitGroup{}
	wg.Add(1)

	ctClient = ue.CybertwinClient{
		Ueid:              apClient.Ueid,
		R3:                apClient.R3,
		Token:             apClient.Token,
		CanRequest:        false,
		Wg:                wg,
		TimerForReconnect: t,
	}
	cli, err = gnet.NewClient(&ctClient)
	if err != nil {
		log.Errorln("runCyberTwinClient:", err.Error())
		return
	}
	err = cli.Start()
	// IP地址和端口号不应该是写死的，应该是AP告知的
	conn, err = cli.Dial("tcp", fmt.Sprintf("%s:%s", apClient.Ct_ip, apClient.Ct_port))
	if err != nil {
		log.Errorln("runCyberTwinClient:", err.Error())
		return
	}

	wg.Wait()
	return
}

func main() {
	err := runAPClient(ueid, hid)
	if err != nil {
		log.Errorln(err.Error())
		return
	}
	conn, _, err := runCyberTwinClient(nil)
	if err != nil {
		log.Errorln("run Cybertwin Client failed")
		return
	}
	log.Infof("UE Client is ready to make request\n")
	makeRequest(conn, 0, 1)
	time.Sleep(time.Second * 5)
}

func makeRequest(conn gnet.Conn, state byte, requestId uint32) {
	ctClient.Req_map[requestId] = &timer.Timer{}
	ctClient.Req_map[requestId].Begin()
	request := []byte("GET / HTTP/1.1\r\n" +
		"Host: www.baidu.com\r\n" +
		"Connection: close\r\n\r\n")

	reqHeader := protocol.Request_Header{
		ProviderID:  uint32(1),
		ServiceID:   uint32(1),
		RequestID:   requestId,
		Token:       0, //ctClient.Token, todo: token传入大小，而不是token本身
		DataSize:    uint32(len(request)),
		Dscp:        7,
		State:       state,
		MaxRespTime: 5,
	}
	body, _ := protocol.CodecUtils.RequestProtocolCodec.AppendHeader(reqHeader, request)
	data, _ := protocol.CodecUtils.AccessProtocolCodec.AESEncode(body, protocol.TYPE_UE_CYBERTWIN_REQUEST, ctClient.Ck3)
	_, err := conn.Write(data)
	if err != nil {
		return
	}
	return

}
